相信用 C 語言寫過檔案讀取的人都知道,經常開檔後就忘記關檔,或者程式中間跳出例外,因此沒有關檔。這些問題常常讓人非常頭痛?。
所幸 Python 中有 with
這個語法糖,可以自動幫你開關檔,跳出例外也難不倒他,真的非常好用。
但你真的了解 with
背後的運行原理嗎? ?
不知道沒關係,因為你現在就會知道了!
在講 with
之前,必須先介紹一下 context manager,中文可以翻成 情境管理器。
為什麼叫做 情境管理器 呢? 我們試想一個情境...
當你進入房間時,就要開啟房間的燈:然後當你離開房間時,就要關閉房間的燈。
像這樣理所當然一定要做的事情,我們就稱為一個情境。而 Python 就是透過情境管理器處理這些情境。
要自己實作 context manager 其實很簡單,只要在 Class 中實作 __enter__()
和 __exit__()
即可。
就以進入房間當作例子。
class Room():
def turn_on_light(self):
print("開燈")
def turn_off_light(self):
print("關燈")
def __enter__(self):
print("進入房間")
self.turn_on_light()
return "在房間裡"
def __exit__(self, exc_type, exc_value, traceback):
self.turn_off_light()
print("離開房間")
with Room() as room:
print(room)
執行之後會印出以下結果:
進入房間
開燈
在房間裡
關燈
離開房間
這非常的直覺,當我們宣告 with Room()
時,就會自動去呼叫 Room()
裡面的 __enter__()
這個函數。後面的 room
就是回傳的字串 "在房間裡" 哦!
當程式離開 with
的範圍時,就會自動去呼叫 __exit__()
這個函數。這多了三個參數分別是 exc_type
(例外型態), exc_value
(例外值), traceback
(錯誤追蹤結果),下一個例子示範如何使用這三個參數。
class Room():
def turn_on_light(self):
print("開燈")
def turn_off_light(self):
print("關燈")
def __enter__(self):
print("進入房間")
self.turn_on_light()
return "在房間裡"
def __exit__(self, exc_type, exc_value, traceback):
if not exc_type:
self.turn_off_light()
print("離開房間")
else:
print("Exception type:", exc_type)
print("Exception value:", exc_value)
print("Traceback:", traceback)
with Room() as room:
print(i) # NameError
執行結果:
進入房間
開燈
Exception type: <class 'NameError'>
Exception value: name 'i' is not defined
Traceback: <traceback object at 0x0000023862DD4700>
Traceback (most recent call last):
File "D:\Andy\Code\test_with\test02.py", line 26, in <module>
print(i)
NameError: name 'i' is not defined. Did you mean: 'id'?
我故意使用一個沒宣告過的變數,讓程式跳出 NameError
,然後就會直接呼叫 __exit__()
,並傳入錯誤訊息的參數。如果正常沒出錯的情況,exc_type
會是 None,就會去執行原本的程式 (關燈)。
所以 Python 常用的 open()
實際上就是一個 context manager,__enter__()
就寫開檔相關的程式,__exit__()
則寫關檔相關的程式,就完成啦!
偶爾去研究一下 Python 一些語法的實作也滿有趣的呢?
小编对如今Paper代写 http://www.pnstudy.com 行业的了解发现,如今总体的市场认同度还是非常好的。大家在代写的过程中不仅可以解决学业问题,最关键的是自己也能从中学习一些自己还未掌握的专业技能。